/**
 * 封装一些基础方法 主要包括
 * 1、判定是否是IE
 * 2、来自dojo的partial和hitch方法，用于函数的作用于绑定和参数绑定
 * 3、来自Underscore的debouce方法和throttle方法。用于避免函数的频繁调用
 * 函数的具体用法见相关文档
 * @author wjm
 * @version 0.0.4
 * @build 2015-03-08
 * @lastday 2015-03-13
 * 		2015-03-13添加debouce和throttle方法
 */
define([ "jquery" ],
		function($) {
	efficient = function(obj, offset, startWith) {
		return (startWith || []).concat(Array.prototype.slice.call(obj,
				offset || 0));
	};
	var lang = {
		isIE : /(msie\s|trident.*rv:)([\w.]+)/.test(navigator.userAgent
				.toLowerCase()),
		hitch : function(scope, method) {
			return function() {
				return method.apply(scope, arguments || []);
			};
		},
		partial : function(/* Function|String */method /* , ... */) {
			var arr = [ null ];
			return lang.hitch.apply(dojo, arr.concat(lang
					._toArray(arguments))); // Function
		},
		// 从underscore中移植的几个方法，用于防止函数被频繁重复调用
		now : Date.now || function() {
			return new Date().getTime();
		},
		debounce : function(func, wait, immediate) {
			var timeout, args, context, timestamp, result;
			var that = this;
			var later = function() {
				var last = that.now() - timestamp;

				if (last < wait && last >= 0) {
					timeout = setTimeout(later, wait - last);
				} else {
					timeout = null;
					if (!immediate) {
						result = func.apply(context, args);
						if (!timeout)
							context = args = null;
					}
				}
			};
			return function() {
				context = this;
				args = arguments;
				timestamp = that.now();
				var callNow = immediate && !timeout;
				if (!timeout)
					timeout = setTimeout(later, wait);
				if (callNow) {
					result = func.apply(context, args);
					context = args = null;
				}
				return result;
			};
		},
		throttle : function(func, wait, options) {
			var that = this;
			var context, args, result;
			var timeout = null;
			var previous = 0;
			if (!options)
				options = {};
			var later = function() {
				previous = options.leading === false ? 0 : that.now();
				timeout = null;
				result = func.apply(context, args);
				if (!timeout)
					context = args = null;
			};
			return function() {
				var now = that.now();
				if (!previous && options.leading === false)
					previous = now;
				var remaining = wait - (now - previous);
				context = this;
				args = arguments;
				if (remaining <= 0 || remaining > wait) {
					if (timeout) {
						clearTimeout(timeout);
						timeout = null;
					}
					previous = now;
					result = func.apply(context, args);
					if (!timeout)
						context = args = null;
				} else if (!timeout && options.trailing !== false) {
					timeout = setTimeout(later, remaining);
				}
				return result;
			};
		},
		isString : function(it) {
			return (typeof it == "string" || it instanceof String); // Boolean
		},
		trim : String.prototype.trim ? function(str) {
			return str.trim();
		} : function(str) {
			return str.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
		},
		_toArray : !$.support.leadingWhitespace ? (function() {
			function slow(obj, offset, startWith) {
				var arr = startWith || [];
				for ( var x = offset || 0; x < obj.length; x++) {
					arr.push(obj[x]);
				}
				return arr;
			}
			return function(obj) {
				return ((obj.item) ? slow : efficient).apply(this,
						arguments);
			};
		})() : efficient
	};
	return lang;
});